home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr09 / vstsrc.zip / VST.C < prev    next >
C/C++ Source or Header  |  1995-02-02  |  44KB  |  1,406 lines

  1. /*
  2.  * %W% %E% %U%  [EXTREL_1.2]
  3.  *
  4.  * VersaTrack orbit calculations are based on those that appear in Dr. Manfred
  5.  * Bester's sattrack program (the Unix(tm) versions 1 and 2).
  6.  *
  7.  * The data from which the maps where generated come from "xsat", an
  8.  * X-Windows program by David A. Curry (N9MSW).
  9.  *
  10.  * Site coordinates come from various sources, including a couple of
  11.  * World Almanacs, and also from both of the programs mentioned above.
  12.  *
  13.  * The following are authors' applicable copyright notices:
  14.  *
  15.  *                                                                               
  16.  * Copyright (c) 1992, 1993, 1994 Manfred Bester. All Rights Reserved.        
  17.  *                                                                           
  18.  * Permission to use, copy, modify, and distribute this software and its      
  19.  * documentation for educational, research and non-profit purposes, without   
  20.  * fee, and without a written agreement is hereby granted, provided that the  
  21.  * above copyright notice and the following three paragraphs appear in all    
  22.  * copies.                                                                    
  23.  *                                                                              
  24.  * Permission to incorporate this software into commercial products may be    
  25.  * obtained from the author, Dr. Manfred Bester, 1636 M. L. King Jr. Way,     
  26.  * Berkeley, CA 94709, USA.                                                   
  27.  *                                                                             
  28.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,  
  29.  * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF    
  30.  * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED   
  31.  * OF THE POSSIBILITY OF SUCH DAMAGE.                                         
  32.  *                                                                             
  33.  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT       
  34.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A    
  35.  * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"       
  36.  * BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,  
  37.  * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.                                   
  38.  *                                                                             
  39.  *                                                                             
  40.  * Copyright 1992 by David A. Curry                                            
  41.  *                                                                             
  42.  * Permission to use, copy, modify, distribute, and sell this software and its 
  43.  * documentation for any purpose is hereby granted without fee, provided that  
  44.  * the above copyright notice appear in all copies and that both that copyright
  45.  * notice and this permission notice appear in supporting documentation.  The  
  46.  * author makes no representations about the suitability of this software for  
  47.  * any purpose.  It is provided "as is" without express or implied warranty.   
  48.  *                                                                             
  49.  * David A. Curry, N9MSW                                                       
  50.  * Purdue University                                                           
  51.  * Engineering Computer Network                                                
  52.  * 1285 Electrical Engineering Building                                        
  53.  * West Lafayette, IN 47907                                                    
  54.  * davy@ecn.purdue.edu                                                         
  55.  *                                                                             
  56.  * VersaTrack Copyright (c) 1993, 1994 Siamack Navabpour. All Rights Reserved.
  57.  *
  58.  * Permission is hereby granted to copy, modify and distribute VersaTrack
  59.  * in whole, or in part, for educational, non-profit and non-commercial use
  60.  * only, free of charge or obligation, and without agreement, provided that
  61.  * all copyrights and restrictions noted herein are observed and followed, and
  62.  * additionally, that this and all other copyright notices listed herein
  63.  * appear unaltered in all copies and in all derived work.
  64.  *
  65.  * This notice shall not in any way void or supersede any of the other authors
  66.  * rights or privileges.
  67.  *
  68.  * VersaTrack IS PRESENTED FREE AND "AS IS", WITHOUT ANY WARRANTY OR SUPPORT.
  69.  * YOU USE IT AT YOUR OWN RISK. The author(s) shall not be liable for any
  70.  * direct, indirect, incidental, or consequential damage, loss of profits or
  71.  * other tangible or intangible losses or benefits, arising out of or related
  72.  * to its use. VersaTrack carries no warranty, explicit or implied, including
  73.  * but not limited to those of merchantablity and fitness for a particular
  74.  * purpose.
  75.  *
  76.  * Siamack Navabpour, 12342 Hunter's Chase Dr. Apt. 2114, Austin, TX 78729.
  77.  * sia@bga.com or sia@realtime.com.
  78.  */
  79.  
  80.  
  81. #include <windows.h>
  82. #include <winsock.h>
  83. #include <math.h>
  84. #include <stdio.h>
  85. #include <stdlib.h>
  86.  
  87. #include "resource.h"
  88. #include "vstdefs.h"
  89. #include "constant.h"
  90. #include "vsttype.h"
  91. #include "vstextrn.h"
  92. #include "vstdib.h"
  93.  
  94. /*
  95.  * Global vars
  96.  */
  97.  
  98. char textbuf[BUFLEN];
  99. char tmpbuf[BUFLEN]; 
  100. char msgbuf[BUFLEN]; 
  101. char string[BUFLEN];
  102. char timeZoneName[9];
  103. char timeZoneHrs[11];
  104. char mapname[16];
  105. char datadir[96];
  106. char SiteName[64];
  107. char VersionStr[40];
  108. char sitefilename[NAMELEN];
  109. char satfilename[NAMELEN];
  110. char activefilename[NAMELEN];
  111. char modesfilename[NAMELEN];
  112. char gtrfilename[NAMELEN];
  113. char mapfilename[NAMELEN];
  114. char rotatorfilename[NAMELEN];
  115. char radiofilename[NAMELEN];
  116. char dllname[NAMELEN] = { "DBREAD.DLL" } ;
  117. char *dllloadmsg = "VersaTrack: Cannot find/load DBREAD.DLL";
  118. char *dllinvalidmsg = "Module not found in DBREAD.DLL";
  119.  
  120. #if 0            /* NOT CURRENTLY USED */
  121. #define UC(x)   ((unsigned char)(x))
  122.  
  123. unsigned char EpochString[18] = {       /* */
  124.     UC(0x38), UC(0x86), UC(0x3b), UC(0x66),
  125.     UC(0x6c), UC(0xee), UC(0xbc), UC(0x24),
  126.     UC(0xc5), UC(0xae), UC(0x37), UC(0x83),
  127.     UC(0xde), UC(0xc1), UC(0xbe), UC(0x41)
  128. };
  129. #endif
  130.  
  131. /*
  132.  * Color table. Use 16-color VGA.
  133.  */
  134. static
  135. COLORREF DefColors[16] = {
  136.     0x00000000, 0x0000007f, 0x00007f00, 0x00007f7f,
  137.     0x007f0000, 0x007f007f, 0x007f7f00, 0x007f7f7f,
  138.     0x00bfbfbf, 0x000000ff, 0x0000ff00, 0x0000ffff,
  139.     0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff
  140. };
  141.  
  142. static
  143. mapsuffix_t mapSuffix[] = {
  144.     640, 480, "64",
  145.     800, 600, "86",
  146.     1024, 768, "17",
  147.     0, 0,
  148. };
  149.  
  150. double      minElevation = 0.0;
  151. double      duration = 1.0;
  152. double      stepTime = 30.0 / SPD;
  153. double      startTime = -1;
  154. double      stopTime = -1;
  155. double      timeZone = 0;
  156. double      ScaleX;
  157. double      ScaleY;
  158.  
  159. site_t      **siteInfo;              /* vector of ptrs to sorted sites      */ 
  160. satellite_t **satInfo;               /* vector of ptrs to element sets      */
  161. select_t    *selInfo;                /* list of user's favorite sat/site tuples */
  162. select_t    *currentSel;             /* currently selected entry in the active list */
  163. rotinfo_t   *rotInfo;                /* linked list of rotator drivers      */
  164. radinfo_t   *radInfo;                /* linked list of radio drivers        */
  165. FILE        *gtrFile;                /* File ptr for ground track report file */
  166. HANDLE      hInst;                   /* VersaTrack instance handle          */
  167. HANDLE      gtr_thread_handle;       /* for thread drawing a groundtrack    */
  168. int         Inst;                    /* int version of hInst.               */
  169. HWND        Gwnd;                    /* global copy of our window handle    */
  170. HWND        rsthwnd;                 /* handle of Rise Time query dialog box*/
  171. HWND        hDlgMenu;                /* VersaTrack's main window menu       */
  172. HBITMAP     hCompatBitmap;           /* handle of copy of screen bitmap     */
  173. HBITMAP     htBitmap;                /* bitmap for drawing text             */
  174. HDC         hCompatDC;               /* correspoding DC's for above         */
  175. HDC         hAppDC;                  /* Our window's DC (style is OWNDC)    */
  176. HDC         htDC;                    /* DC for bitmap for drawing text      */
  177. HPEN        hDrawPen[NPAL];          /* All the colored pen handles         */
  178. HBRUSH      hDrawBrush[NPAL];        /* All the colored brush handles       */
  179. HFONT       hArial,hHelv,hPica;      /* Font of text for htDC               */
  180. COLORREF    BgColor, FgColor;        /* System Defaults for FG & BG         */
  181. COLORREF    Colors[NPAL];            /* colors we can use...                */
  182. HCURSOR     hcurSave;                /* for previous                        */
  183. HCURSOR     hWait;                   /* handle of hourglass cursor icon     */
  184. HCURSOR     hMenuCursor;             /* handle of main window menu's cursor */
  185. RECT        tRect;                   /* Text area at bottom of screen       */
  186. static HICON hAsterisk, hQuestion;   /* Icon handles                        */
  187. HICON       hVersa;                  /* Main Versatrak Icon Handle          */
  188. int         width = 750;             /* Default width of client area (map)  */
  189. int         height = 400;            /* Default height of client area (map  */
  190. int         Inst;                    /* Window Class Instance handle        */
  191. int         npal, ncolor;            /* # of available colors               */
  192. int         PenColor;                /* current pen color                   */
  193. int         BrushColor;              /* current brush color                 */
  194. int         TextColor;               /* current pen for drawing text        */
  195. int         CWhite, CBlack;          /* Index into pen/brush color tables   */
  196. int         DefBg, DefFg;            /* index into pen/brush color tables   */
  197. int         currx_client;            /* current Client area width           */
  198. int         curry_client;            /* current Client area height          */
  199. int         extra_x;                 /* these plus ClRect = total window size */
  200. int         extra_y;                 /* these plus ClRect = total window size */
  201. int         ybottom = 20;            /* extra space at bottom for text line */
  202. int         ytop = 46;               /* extra rasters at top for custom menu*/
  203. int         maxx_device;             /* Max # of pixels the window can have */
  204. int         maxy_device;             /* Max # of pixels the window can have */
  205. RECT        tRect;                   /* Text area at bottom of screen       */
  206. int         running;                 /* TRUE when RTD prediction is running */
  207. int         pending;                 /* user command to do after RTD stops  */
  208. int         duration_running;        /* TRUE when groundtrack is running    */
  209. int         duration_stop;           /* signal to GTR thread to terminate   */
  210. int         modelflag=NORADSGP4;     /* Elset propagation model 0:TLEMEAN 1:SGP4 2:SPD4 */
  211. int         NSats,NSites;            /* No. of satellites and sites in DB   */
  212. void        (*diag)(char *, ...);    /* printf-line func. for debugging     */
  213. static int oct[7] = { 440, 494, 523, 587, 659, 698, 784 }; /* Musical Notes A-G */
  214. mapdata_t   mapdata;                 /* Current map's x and y extents       */
  215. static char *mapsuffix;              /* Suffix for map file to be drawn     */
  216. CRITICAL_SECTION  display_mutex;     /* Mutex lock for updates to screen    */
  217. CRITICAL_SECTION  sat_mutex;         /* Mutex lock access to sat struct     */
  218.  
  219. extern BOOL DrawMap(void);
  220. extern void vsthelp(void);
  221. extern void SetMButton(UINT, BOOL);
  222. extern char *ErrorString(int);
  223. #ifndef _DEBUG_
  224. void nullfunc(char *s, va_list va) { }
  225. #endif /* _DEBUG_ */
  226.  
  227.  
  228. int WINAPI WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  229. HANDLE hInstance;
  230. HANDLE hPrevInstance;
  231. LPSTR lpCmdLine;
  232. int nCmdShow;
  233. {
  234.     MSG msg;
  235.     extern BOOL InitInstance(HANDLE, HANDLE, int);
  236.     extern BOOL InitApplication(HANDLE);
  237.     select_t *sp;
  238.  
  239.     hInst = hInstance;
  240.  
  241.     if (!InitApplication(hInstance))
  242.         return FALSE;
  243.  
  244.     if (!InitInstance(hInstance, hPrevInstance, nCmdShow))
  245.         return FALSE;
  246.  
  247.     while (GetMessage(&msg, (UINT)NULL, (UINT)NULL, (UINT)NULL)) {
  248.         for (sp = selInfo; sp; sp = sp->sl_next)
  249.             if (sp->rtdhwnd && msg.hwnd == sp->rtdhwnd)
  250.                 if (IsDialogMessage(sp->rtdhwnd, &msg))
  251.                     goto next;
  252.         if (msg.message == VST_NOP)
  253.             msg.hwnd = Gwnd;
  254.  
  255.         TranslateMessage(&msg);
  256.         DispatchMessage(&msg);
  257.       next: ;
  258.     }
  259.     DestroyObjects();
  260.     return 0; /* When program exits */
  261. }
  262.  
  263.  
  264. BOOL InitApplication(hInstance)
  265. HANDLE hInstance;
  266. {
  267.     WNDCLASS wc;
  268.     extern BOOL CALLBACK VersaTrackWindowProc();
  269.  
  270.     hVersa    = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_VSTICON));
  271.     hAsterisk = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ASTERISK));
  272.     hQuestion = LoadIcon(NULL, MAKEINTRESOURCE(IDI_QUESTION));
  273.     hWait     = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
  274.     hcurSave  = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_VSTCIRCLE));
  275.     sprintf(VersionStr,"VersaTrack V%d.%d",VSTVERSION/10,VSTVERSION%10);
  276.     
  277.     wc.style = CS_OWNDC;           /* CS_VREDRAW | CS_HREDRAW;  */
  278.     wc.lpfnWndProc = (WNDPROC) VersaTrackWindowProc;
  279.     wc.cbClsExtra = 0;
  280.     wc.cbWndExtra = 0;
  281.     wc.hInstance = hInstance;
  282.     wc.hIcon = hVersa;
  283.     wc.hCursor = hcurSave;
  284.     wc.hbrBackground = NULL;
  285.     wc.lpszClassName = "VERSATRACK";
  286.     wc.lpszMenuName = NULL;
  287.  
  288.     return RegisterClass(&wc);
  289. }
  290.  
  291. BOOL InitInstance(hInstance, hPrevInstance, nCmdShow)
  292. HANDLE hInstance, hPrevInstance;
  293. int    nCmdShow;
  294. {
  295.     HWND hWnd;
  296.  
  297.     hInst = hInstance;
  298.     hWnd = CreateWindow("VERSATRACK", VersionStr,
  299.         WS_OVERLAPPEDWINDOW|WS_BORDER|WS_CLIPCHILDREN, /* Window style.  */
  300.         0, 0, width, height,
  301.         NULL,                        /* Overlapped windows have no parent.*/
  302.         NULL,                        /* Use the window class menu.        */
  303.         hInstance,                   /* This instance owns this window.   */
  304.         NULL                         /* Pointer not needed.               */
  305.     );
  306.     if (hWnd == NULL)
  307.             return FALSE;
  308.  
  309.     Gwnd = hWnd;
  310.     return TRUE;
  311. }
  312.  
  313. BOOL CALLBACK
  314. VersaTrackWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  315. {
  316.     int cmd;
  317.     select_t *sp;
  318.     int (*GetUserInput)(HWND, char *, char *, char *, int);
  319.     extern void *LibFunc(const char *), LibClose(void);
  320.     static char *busymsg = "Cannot change while busy";
  321. #ifdef _DEBUG_
  322.     extern int debugflag;
  323. #endif /* _DEBUG_ */
  324.  
  325.     Gwnd = hWnd;
  326.           
  327.     switch (message) {        
  328.     case WM_CREATE:
  329. #ifdef _DEBUG_
  330.         diag = DebugFunc;
  331.         debugflag = 1;
  332. #else /* _DEBUG_ */
  333.         diag = nullfunc;
  334. #endif /* _DEBUG_ */
  335.         WaitCursor();
  336.         InitGraphics();
  337.         if (!init_main()) {
  338.             PostQuitMessage(0);
  339.             break;
  340.         }
  341.         if (!DrawMap()) {
  342.             PostQuitMessage(0);
  343.             break;
  344.         }
  345.         NormCursor();
  346.         if (!GetSystemMetrics(SM_MOUSEPRESENT))
  347.             fatal("VersaTrack requires the use of a mouse!");
  348.         break;
  349.  
  350.     case WM_CANCELMODE:
  351.         ReleaseCapture();
  352.         break;
  353.         
  354.     case WM_PAINT:
  355.         if (IsIconic(hWnd))
  356.             goto defaction;   
  357.         PaintWindow();
  358.         break;
  359.  
  360.     case WM_ERASEBKGND:
  361.         return 1L;
  362.  
  363.     case WM_GETMINMAXINFO:
  364.         ((MINMAXINFO *)lParam)->ptMinTrackSize.x = width + extra_x;
  365.         ((MINMAXINFO *)lParam)->ptMinTrackSize.y = height + extra_y + ytop;
  366.         ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = width + extra_x;
  367.         ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = height + extra_y + ytop + ybottom - 1;
  368.         break;
  369.  
  370.     case VST_NOP:
  371. #ifdef _DEBUG_
  372.         diag("Received VST_NOP %08x %08x\n", wParam, lParam);
  373. #endif /* _DEBUG_ */
  374.         break;
  375.  
  376.     case RTD_LONGBEEPUP:
  377.         if (InSendMessage())
  378.             ReplyMessage(TRUE);
  379.         for (cmd = 0; cmd < 8; cmd++) {
  380.             Beep(oct[cmd], 40);
  381.             Sleep(80);
  382.         }
  383.         break;
  384.     case RTD_LONGBEEPDOWN:
  385.         if (InSendMessage())
  386.             ReplyMessage(TRUE);
  387.         for (cmd = 8; cmd >= 0; cmd--) {
  388.             Beep(oct[cmd], 40);
  389.             Sleep(80);
  390.         }
  391.         break;
  392.  
  393.     case EXTM_THEXIT:
  394.         WaitForSingleObject((HANDLE) lParam, (DWORD) 5000);
  395.         CloseHandle((HANDLE) lParam);
  396.         break;
  397.  
  398.     case RTD_THDEXIT:
  399.         sp = (select_t *) lParam;
  400.         if (sp->rtd_thread_handle) {
  401.             WaitForSingleObject(sp->rtd_thread_handle, (DWORD) 5000);
  402.             CloseHandle(sp->rtd_thread_handle);
  403.         }
  404.         rtd_lock(sp);
  405.         sp->rtd_thread_handle = NULL;
  406.         sp->terminate = sp->running = 0;
  407.         rtd_unlock(sp);
  408.         if (!rtd_anythread()) {
  409.             running = 0;
  410.             PostMessage(hWnd, RTD_ALL_THREADS_FINISHED, (WPARAM) 0, (LPARAM) 0);
  411.         }
  412.         break;
  413.         
  414.     case RTD_WINEXIT:
  415.         sp = (select_t *) lParam;
  416.         rtd_lock(sp);
  417.         sp->rtdhwnd = NULL;
  418.         rtd_unlock(sp);
  419.         if (!rtd_anythread()) {
  420.             running = 0;
  421.             PostMessage(hWnd, RTD_ALL_THREADS_FINISHED, (WPARAM) 0, (LPARAM) 0);
  422.         }
  423.         break;
  424.  
  425.     case RTD_TRUNNING:
  426.     case RTD_WRUNNING:
  427.         running = 1;
  428.         if (rtd_allrunning())
  429.             NormCursor();
  430.         break;
  431.  
  432.     case RTD_STOPPED:
  433.         sp = (select_t *) lParam;
  434.         rtd_lock(sp);
  435.         sp->flags &= ~SE_THSTOP;
  436.         rtd_unlock(sp);
  437.         if (rtd_allstopped())
  438.             PostMessage(hWnd, RTD_ALL_THREADS_STOPPED, (WPARAM) 0, (LPARAM) 0);
  439.         break;
  440.  
  441.     case GTR_QUIT:
  442.         duration_running = duration_stop = 0;
  443.         WaitForSingleObject(gtr_thread_handle, (DWORD) 15000);
  444.         CloseHandle(gtr_thread_handle);
  445.         gtr_thread_handle = NULL;
  446.         NormCursor();
  447.         if (!rtd_anythread()) {
  448.             running = 0;
  449.             PostMessage(hWnd, RTD_ALL_THREADS_FINISHED, (WPARAM) 0, (LPARAM) 0);
  450.         }
  451.         break;
  452.  
  453.     case RTD_ALL_THREADS_FINISHED:
  454.         if (InSendMessage())
  455.             ReplyMessage(TRUE);
  456.  
  457.         NormCursor();
  458.  
  459.         if (pending == PEND_NONE)
  460.             break;
  461.  
  462.         switch (pending) {
  463.         case PEND_DURATION_PREDICT:
  464.             if (!duration_running && !duration_stop)
  465.                 duration_predict(currentSel);
  466.             break;
  467.  
  468.         case PEND_EXITPROGRAM:
  469.             goto exitprog;
  470.             break;
  471.  
  472.         default:
  473.             break;
  474.         }
  475.         pending = PEND_NONE;
  476.         break;
  477.  
  478.     case RTD_ALL_THREADS_STOPPED:            
  479.         switch(pending) {
  480.         case PEND_DRAWMAP:
  481.             DrawMap();
  482.             break;
  483.         default:
  484.             break;
  485.         }
  486.         pending = PEND_NONE;
  487.         NormCursor();
  488.         break;
  489.  
  490.     case RTD_DORESUME:        
  491.         SetROP2(hCompatDC, R2_XORPEN);
  492.         rtd_allresume();
  493.         break;
  494.         
  495.      case WM_SYSCOMMAND:
  496.         if (wParam == SC_MINIMIZE)
  497.             rtd_savewindowstate();
  498.         goto defaction;
  499.  
  500.      case WM_COMMAND:
  501.         cmd = LOWORD(wParam);
  502.  
  503.         switch (cmd) {
  504.             extern void GetSettings(void), copyrights();
  505.             case IDMD_XX1:
  506.             case IDMD_XX2:
  507. #ifdef _DEBUG_
  508.                 { extern void thdump(BOOL);    thdump(FALSE); }
  509. #endif /* _DEBUG_ */
  510.                 break;
  511.             case IDMD_QUIT:
  512.                 if (running) {
  513.                     if (yesno("Are you sure you want to exit VersaTrack ?")) {
  514.                         pending = PEND_EXITPROGRAM;
  515.                         continuous_display_finish(NULL);
  516.                     }
  517.                     break;
  518.                 }
  519.                 else goto exitprog;
  520.  
  521.             case IDMD_ABOUT:
  522.                 copyrights();
  523.                 break;
  524.  
  525.             case IDMD_HELP:
  526.                 vsthelp();
  527.                 break;
  528.  
  529.             case IDMD_GTRFILENAME:
  530.                 GetUserInput = (void (*)) LibFunc("GetUserInput");
  531.                 if (GetUserInput == NULL)
  532.                     usermsg("Invalid Library");
  533.                 else {
  534.                     (*GetUserInput)(hWnd,
  535.                         "Enter Ground Track Report file name:",
  536.                         gtrfilename, gtrfilename, sizeof(gtrfilename) -1);
  537.                 }
  538.                 LibClose();
  539.                 break;
  540.  
  541.             case IDMD_SETCOLOR:
  542.                 SetColors();
  543.                 break;
  544.  
  545.             case IDMD_UNINSTALL:
  546.                 if (UnInstall(VSTVERSION)) {
  547.                     if (running) {
  548.                         pending = PEND_EXITPROGRAM;
  549.                         continuous_display_finish(NULL);
  550.                     }
  551.                     else {
  552.                         goto exitprog;
  553.                     }
  554.                 }
  555.                 break;
  556.                 
  557.             case IDMD_SETTINGS:
  558.                 GetSettings();
  559.                 break;
  560.                 
  561.             case IDMD_WORLDMAP:
  562.                 strcpy(mapname,"world");
  563.                 goto drawmap;
  564.                 
  565.             case IDMD_USAMAP:
  566.                 strcpy(mapname, "usa");
  567.                 /* FALL THROUGH */
  568.  
  569.             case IDMD_REDRAWMAP:
  570.             drawmap:
  571.                 if (pending)
  572.                     break;
  573.                 if (running && !duration_running) {
  574.                     pending = PEND_DRAWMAP;
  575.                     WaitCursor();
  576.                     rtd_allstop();
  577.                 }
  578.                 else if (duration_running && !running) {
  579.                     usermsg("Stop GTR first!");
  580.                     break;
  581.                 }
  582.                 else {
  583.                     WaitCursor();
  584.                     DrawMap();
  585.                     NormCursor();
  586.                 }
  587.                 break;
  588.             case IDMD_RUNRTD:
  589.                 continuous_display_init(NULL);
  590.                 break;
  591.  
  592.             case IDMD_RUNGTR:
  593.                 if (running && !pending) {
  594.                     pending = PEND_DURATION_PREDICT;
  595.                     continuous_display_finish((select_t *)NULL);
  596.                 }  
  597.                 else if (!duration_running && !duration_stop) {
  598.                     if (currentSel)
  599.                         duration_predict(currentSel);
  600.                     else if (selInfo)
  601.                         duration_predict(selInfo);
  602.                 }
  603.                 break;
  604.             case IDMD_RUNRST:
  605.                 rst ( currentSel ? currentSel : selInfo);
  606.                 break;
  607.                 
  608.             case IDMD_STOP:
  609.                 if (running && (pending == PEND_NONE)) {
  610.                     continuous_display_finish((select_t *)NULL);
  611.                 }
  612.                 else if (!running && duration_running) {
  613.                     duration_stop = 1;
  614.                     
  615.                 }
  616.                 break;
  617.                 
  618.             case IDMD_RADCNTRL:
  619.                 (void) ServerCreate(&serverInfo[SRV_RADIO], (void *)&radInfo[0]);
  620.                 break;
  621.                 
  622.             case IDMD_ROTCNTRL:
  623.                 (void ) ServerCreate(&serverInfo[SRV_ROTATOR], (void *)&rotInfo[0]);
  624.                 break;
  625.             }
  626.         break;
  627.  
  628.     case WM_LBUTTONUP:
  629.         if (!running || duration_running)
  630.             break;
  631.         sp = checksat(LOWORD(lParam), HIWORD(lParam));
  632.         if (sp)
  633.             PostMessage(sp->rtdhwnd, RTD_TOGGLE_ICON, (WPARAM)0, (LPARAM)0);
  634.         break;
  635.  
  636.     case WM_MOUSEACTIVATE:
  637.         return MA_ACTIVATE;
  638.  
  639.     case WM_CLOSE:
  640.         if (running) {
  641.             if (yesno("Are you sure you want to exit VersaTrack ?")) {
  642.                 pending = PEND_EXITPROGRAM;
  643.                 continuous_display_finish(NULL);
  644.                 if (duration_running)
  645.                     duration_stop = 1;
  646.             }
  647.             break;
  648.         }
  649.         goto defaction;
  650.  
  651.     case WM_DESTROY:
  652.     exitprog:
  653.         PostQuitMessage(0);
  654.         break;
  655.  
  656.     default:
  657.     defaction:
  658.         return DefWindowProc(hWnd, message, wParam, lParam);
  659.     }
  660.     return 0L;
  661. }
  662.  
  663. /*
  664.  * usermsg() - opens a dialog box and posts an informative message. Returns
  665.  * when user clicks on the YES button. This is just to write a message.
  666.  */
  667.  
  668. void
  669. usermsg(msg)
  670. char *msg;
  671. {
  672.     strncpy(msgbuf,msg,sizeof(msgbuf)-1);
  673.  
  674.     if (IsIconic(Gwnd)) {
  675.         OpenIcon(Gwnd);
  676.         EnableWindow(Gwnd, TRUE);
  677.     }
  678.     DialogBox(hInst, MAKEINTRESOURCE(IDD_MESSAGE), Gwnd, UserMsgProc);
  679.     EnableWindow(Gwnd, TRUE);
  680.     UpdateWindow(Gwnd);
  681. }
  682.  
  683. int
  684. yesno(msg)
  685. char *msg;
  686. {
  687.     int r;
  688.     extern BOOL CALLBACK YesNoProc();
  689.     
  690.     strncpy(msgbuf,msg, sizeof(msgbuf)-1);
  691.  
  692.     if (IsIconic(Gwnd)) {
  693.         OpenIcon(Gwnd);
  694.         EnableWindow(Gwnd, TRUE);
  695.     }
  696.  
  697.     r = DialogBox(hInst, MAKEINTRESOURCE(IDD_YESNO), Gwnd, YesNoProc);
  698.     UpdateWindow(Gwnd);
  699.  
  700.     return r;
  701. }
  702.  
  703. static void
  704. GetSettings()
  705. {
  706.     extern BOOL CALLBACK GetSetProc();
  707.     static int r;
  708.  
  709.     if (r)
  710.         return;
  711.     r++;
  712.     if (IsIconic(Gwnd))
  713.         OpenIcon(Gwnd);
  714.  
  715.     WaitCursor();
  716.     DialogBox(hInst, MAKEINTRESOURCE(IDD_SETTINGS), Gwnd, GetSetProc);
  717.     NormCursor();
  718.     r = 0;
  719. }
  720.  
  721. /*
  722.  * UserMsgProc - dialog box window procedure. This dialog box is used
  723.  * to put up various messages for the user. It only has a (big) OK button.
  724.  */
  725.  
  726. BOOL CALLBACK UserMsgProc(hwnd, message, wParam, lParam)
  727. HWND hwnd;
  728. UINT message;
  729. WPARAM wParam;
  730. LPARAM lParam;
  731. {
  732.     int action;
  733.     POINT *p;
  734.     HDC hdc;
  735.         
  736.     switch(message) {
  737.     case WM_INITDIALOG:
  738.         p = DialogPos(Gwnd, hwnd);
  739.         SendDlgItemMessage(hwnd, IDC_MSGTEXT, WM_SETTEXT, (WPARAM)0, (LPARAM)msgbuf);
  740.         SetWindowPos(hwnd, HWND_TOPMOST, (int)p->x, (int)p->y, 0, 0,
  741.             SWP_NOSIZE|SWP_SHOWWINDOW);
  742.         hdc = GetDC(hwnd);
  743.         DrawIcon(hdc, 12, 17, hAsterisk);
  744.         ReleaseDC(hwnd, hdc);
  745.         break;
  746.  
  747.     case WM_COMMAND:
  748.         action = LOWORD(wParam);
  749.         if (action == IDOK) {
  750.             EndDialog(hwnd, wParam);
  751.             return TRUE;
  752.         }
  753.         break;
  754.  
  755.     case WM_CTLCOLORDLG:
  756.     case WM_CTLCOLORSTATIC:
  757.         ColorSet(wParam, CBLACK, 14);
  758.         return (BOOL) hDrawBrush[14];
  759.  
  760.     default:
  761.         break;
  762.     }
  763.     return FALSE;
  764. }
  765.  
  766. /*
  767.  * YesNoProc - window procedure for messages that solicit a yes or no
  768.  * answer from the user. 
  769.  */
  770. BOOL CALLBACK YesNoProc(hwnd, message, wParam, lParam)
  771. HWND hwnd;
  772. UINT message;
  773. WPARAM wParam;
  774. LPARAM lParam;
  775. {
  776.     int action;
  777.     POINT *p;
  778.     HDC hdc;
  779.  
  780.     switch(message) {
  781.     case WM_INITDIALOG:
  782.         p = DialogPos(Gwnd, hwnd);
  783.         SendDlgItemMessage(hwnd, IDC_YESNOTEXT, WM_SETTEXT, 0, (LPARAM) msgbuf);
  784.         SendMessage(hwnd, DM_SETDEFID, (WPARAM) IDOK, (LPARAM) 0);
  785.         SetWindowPos(hwnd, HWND_TOPMOST, (int)p->x, (int)p->y, 0, 0,
  786.             SWP_NOSIZE | SWP_SHOWWINDOW);
  787.         hdc = GetDC(hwnd);
  788.         DrawIcon(hdc, 14, 20, hQuestion);
  789.         ReleaseDC(hwnd, hdc);
  790.         break;
  791.  
  792.     case WM_COMMAND:
  793.         action = LOWORD(wParam);
  794.         if (action == IDOK || action == IDCANCEL) {
  795.             EndDialog(hwnd, (LOWORD(wParam) == IDOK) ? TRUE : FALSE);
  796.             SetFocus(GetParent(hwnd));
  797.             EnableWindow(GetParent(hwnd), TRUE);
  798.             return TRUE;
  799.         }
  800.         break;
  801.  
  802.     case WM_CTLCOLORSTATIC:
  803.     case WM_CTLCOLORDLG:
  804.         ColorSet(wParam, 11, 7); /* 10=light yellow, 6=dark cyan, 5=dark magenta */
  805.         return (BOOL) hDrawBrush[7];        
  806.     }
  807.     return FALSE;
  808. }
  809.  
  810.  
  811. /*
  812.  * Refresh window's actual client area from our copy, based upon the current
  813.  * update region passed to us by Windows.
  814.  */
  815. static void
  816. PaintWindow()
  817. {
  818.     RECT UR;
  819.     PAINTSTRUCT ps;
  820.  
  821.     if (GetUpdateRect(Gwnd, &UR, FALSE) == FALSE)
  822.         return;
  823.     (void) BeginPaint(Gwnd, &ps);
  824.     BitBlt(ps.hdc, (int)UR.left, (int)UR.top, (int)UR.right,
  825.            (int)UR.bottom, hCompatDC, (int)UR.left, (int)UR.top, SRCCOPY);
  826.  
  827.     EndPaint(Gwnd, &ps);
  828. }
  829.  
  830.  
  831. /*
  832.  * InitGraphics() - one-time initialization to set up all the graphics
  833.  * related parameters, arrays, colors, DC handles, mapping modes, etc.
  834.  */
  835. static void
  836. InitGraphics()
  837. {
  838.     int i;
  839.     mapsuffix_t *msp;
  840.     LOGPEN lpen;
  841.     LOGBRUSH lbrush;
  842.  
  843.     BgColor =     GetSysColor(COLOR_WINDOW);
  844.     FgColor =     GetSysColor(COLOR_WINDOWTEXT);
  845.     maxx_device = GetSystemMetrics(SM_CXSCREEN);
  846.     maxy_device = GetSystemMetrics(SM_CYSCREEN);
  847.     
  848. #ifdef _DEBUG_
  849.     diag("device maximum width %d\n", maxx_device);
  850.     diag("device maximum height %d\n", maxy_device);
  851. #endif
  852.  
  853.     extra_x = GetSystemMetrics(SM_CXFRAME) * 2;
  854.     extra_y = GetSystemMetrics(SM_CYFRAME) * 2 +
  855.               GetSystemMetrics(SM_CYCAPTION);
  856.  
  857.     hAppDC    = GetDC(Gwnd);      
  858.     hCompatDC = CreateCompatibleDC((HDC)NULL);
  859.     htDC      = CreateCompatibleDC((HDC)NULL);
  860.     htBitmap  = CreateCompatibleBitmap(hAppDC, 300, 24); /* for drawing text */
  861.     
  862.     ASSERT(hAppDC);
  863.     ASSERT(hCompatDC);
  864.     ASSERT(htDC);
  865.     ASSERT(htBitmap);
  866.     
  867.     SelectObject (htDC, htBitmap);
  868.  
  869.     hArial = CreateFont (12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
  870.       ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  871.       DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helvetica" );
  872.       
  873.     hHelv = CreateFont (16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
  874.       ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  875.       DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helv" );
  876.  
  877.     hPica = CreateFont (12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
  878.       ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  879.       DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "Courier" );
  880.  
  881.     ASSERT(hArial);
  882.     ASSERT(hHelv);
  883.     ASSERT(hPica);
  884.  
  885.     GdiSetBatchLimit(1);
  886.     SetBkMode(htDC, TRANSPARENT);
  887.     SetMapMode(htDC, MM_ISOTROPIC);
  888.     SetWindowExtEx(htDC, 300, 24, NULL);
  889.     SetViewportExtEx(htDC, 300, 24, NULL);
  890.     SetBkMode(hCompatDC, OPAQUE);
  891.  
  892.     ncolor = NPAL;
  893.     CBlack = DefBg = 0;
  894.     CWhite = DefFg = 15;
  895.  
  896.     for (i=0; i < ncolor; i++) {
  897.         Colors[i] = GetNearestColor(hAppDC, DefColors[i]);
  898.         if (Colors[i] == RGB(0,0,0))
  899.             CBlack = i;
  900.         if (Colors[i] == RGB(255,255,255))
  901.             CWhite = i;
  902.         if (Colors[i] == BgColor)
  903.             DefBg = i;
  904.         if (Colors[i] == FgColor)
  905.             DefFg = i;
  906.  
  907.         lpen.lopnStyle   = PS_SOLID;
  908.         lpen.lopnWidth.x = PENWIDTH;
  909.         lpen.lopnWidth.y = 0;
  910.         lpen.lopnColor   = Colors[i];
  911.  
  912.         if ((hDrawPen[i]  = CreatePenIndirect(&lpen)) == NULL)
  913.             fatal("Can't create Pen");
  914.  
  915.         lbrush.lbStyle   = BS_SOLID;
  916.         lbrush.lbHatch   = 0;
  917.         lbrush.lbColor   = Colors[i];
  918.  
  919.         if ((hDrawBrush[i] = CreateBrushIndirect(&lbrush)) == NULL)
  920.             fatal("Can't create Brush");
  921.     }
  922.  
  923.     /*
  924.      * Default map file name suffix. If no match, assume custom name...
  925.      */
  926.  
  927.     mapsuffix = "oem";
  928.     for (msp = mapSuffix; msp->ms_suffix; msp++)
  929.         if ((msp->ms_x == maxx_device) && (msp->ms_y == maxy_device))
  930.             mapsuffix = msp->ms_suffix;
  931.  
  932.     while (ShowCursor(FALSE) >=0 ) ;  /* remove anomalous show states */
  933.     ShowCursor(TRUE);
  934.  
  935.     /* Default ssp, sat annotatation, and ground trk line colors */
  936.  
  937.     MakeBrush(hCompatDC, BrushColor=15);    /* White */
  938.     MakePen(hCompatDC, PenColor=8);         /* Light Grey */
  939.     TextColor = 14;                         /* Light Cyan */
  940. }
  941.  
  942.  
  943. void
  944. MakePen(hdc,index)
  945. HDC hdc;
  946. int index;
  947. {
  948.       if ((index < 0) || (index >= ncolor))
  949.             index = CWHITE;
  950.  
  951.       SelectObject(hdc, (HGDIOBJ) hDrawPen[index]);
  952. }
  953.  
  954. void
  955. MakeBrush(hdc, index)
  956. HDC hdc;
  957. int index;
  958. {
  959.        if ( index < 0 || index > ncolor )
  960.             index = DEFBG;
  961.  
  962.        SelectObject(hdc, (HGDIOBJ) hDrawBrush[index]);
  963. }
  964.  
  965. void
  966. blankBottom()
  967. {        
  968.     tRect.top = height + ytop + 2; /* +2 allows for an unpainted(black) separating raster */
  969.     tRect.bottom = tRect.top + ybottom;
  970.     tRect.left = 0;
  971.     tRect.right = tRect.left + width;
  972.     FillRect(hCompatDC, &tRect, hDrawBrush[8]);
  973. }
  974.  
  975. static BOOL
  976. DrawMap()
  977. {
  978.     HBITMAP     htmp;
  979.     HDC         htmpDC;
  980.     BOOL        mapchanged;
  981.     extern BOOL CALLBACK VSTMenuProc();
  982.     extern void *LibFunc(const char *), LibClose(void);
  983.     HANDLE (*ReadBitmap)(int, char *, int, int *, int *, mapdata_t *);
  984. #ifdef MAPALIGN
  985.     extern void MapPoint(double, double, int, char *);
  986. #endif
  987.  
  988.     sprintf(tmpbuf, "%s%s.map", mapname, mapsuffix);
  989.     mapchanged = strcmp(mapfilename, tmpbuf) != 0;
  990.     
  991.     if (mapchanged)
  992.         strncpy(mapfilename, tmpbuf, sizeof(mapfilename)-1);
  993.         
  994.     sprintf(tmpbuf, "%s\\%s", datadir, mapfilename);
  995.  
  996. #ifdef _DEBUG_
  997.     diag("Drawing map from %s\n", tmpbuf);
  998. #endif /* _DEBUG_ */
  999.  
  1000.     ReadBitmap = (void (*)) LibFunc("ReadDIB");
  1001.     if (ReadBitmap == NULL) {
  1002.         LibClose();
  1003.         usermsg(dllinvalidmsg);
  1004.         return FALSE;
  1005.     }
  1006.  
  1007.     htmp = (HBITMAP) (*ReadBitmap)(VSTVERSION, tmpbuf, 0, &width, &height, &mapdata);
  1008.     
  1009.     if (htmp == NULL) {
  1010.         LibClose();
  1011.         sprintf(tmpbuf, "Cannot open/read map file %s", mapfilename);
  1012.         usermsg(tmpbuf);
  1013.         UnInstall(VSTVERSION);
  1014.         return FALSE;
  1015.     }
  1016.  
  1017. #ifdef DEBUG
  1018.     diag("map file opened. Width %d height %d\n", width, height);
  1019. #endif /* _DEBUG_ */
  1020.  
  1021.     if ((width > maxx_device) || (height > maxy_device)) {
  1022.         LibClose();
  1023.         sprintf(tmpbuf, "%s not suitable for current display resolution", mapfilename);
  1024.         usermsg(tmpbuf);
  1025.         UnInstall(VSTVERSION);
  1026.         return FALSE;
  1027.     }
  1028.     if (mapdata.m_version > VSTVERSION)
  1029.         usermsg("Map may be incompatible with this VersaTrack version.");
  1030.  
  1031.     display_lock();
  1032.     if (mapchanged) {
  1033.             if (hCompatBitmap)
  1034.                 DeleteObject(hCompatBitmap);
  1035.             hCompatBitmap = CreateCompatibleBitmap(hAppDC,
  1036.                                 width, height + ytop + ybottom);
  1037.             SelectObject(hCompatDC, hCompatBitmap);
  1038.     }
  1039.     htmpDC = CreateCompatibleDC((HDC)NULL);
  1040.  
  1041.     if ((hCompatBitmap == NULL) || (htmpDC == NULL)) {
  1042.         display_unlock();
  1043.         usermsg("Cannot Create Device Context or Compatible Bitmap");
  1044.         LibClose();
  1045.         return FALSE;
  1046.     }
  1047.  
  1048.     SelectObject(htmpDC, htmp);
  1049.  
  1050.     BitBlt(hCompatDC, 0, ytop, width, height, htmpDC, 0, 0, SRCCOPY);
  1051.     
  1052.     DeleteObject(htmp);
  1053.     DeleteObject(htmpDC);    
  1054.     LibClose();
  1055.  
  1056.     blankBottom();
  1057.  
  1058.     setwsize(Gwnd, FALSE);
  1059.     
  1060.     SetMapMode(hCompatDC, MM_ISOTROPIC);
  1061.     SetWindowExtEx(hCompatDC, width, height, NULL);
  1062.     SetViewportExtEx(hCompatDC, width, height, NULL);
  1063.  
  1064.     RedrawScreen(NULL);
  1065.     display_unlock();    
  1066.  
  1067. #ifdef MAPALIGN
  1068.     MapPoint(60.0, 45.0, SRCPAINT, "X"); /* southern tip of GreenLand (approx) */
  1069.     MapPoint(38.8975, 77.0092, SRCPAINT, "Washington");
  1070.     MapPoint(29.76, 95.36, SRCPAINT, "Houston");
  1071.     MapPoint(37.3378, 121.89, SRCPAINT, "San Jose");
  1072. #endif
  1073.  
  1074.     if (!hDlgMenu)
  1075.         hDlgMenu = CreateDialog(hInst, MAKEINTRESOURCE(IDD_VSTMENU), Gwnd, VSTMenuProc);
  1076.  
  1077.     if (running)
  1078.         PostMessage(Gwnd, RTD_DORESUME, (WPARAM) 0, (LPARAM) 0);
  1079.  
  1080.     return TRUE;
  1081. }
  1082.  
  1083. static void
  1084. DestroyObjects()        /* half-hearted */
  1085. {
  1086.     int i;
  1087.     select_t *sp;
  1088.     void *vp;
  1089.     extern void ServerDestroy(void);
  1090.  
  1091.     WaitCursor();
  1092.     ServerDestroy();
  1093.     Sleep(0);
  1094.     
  1095.     if (hDlgMenu)
  1096.         DestroyWindow(hDlgMenu);
  1097.  
  1098.     if (rsthwnd)
  1099.         DestroyWindow(rsthwnd);
  1100.  
  1101.     if (htBitmap)
  1102.         DeleteObject(htBitmap);
  1103.  
  1104.     if (htDC)
  1105.         DeleteObject(htDC);
  1106.  
  1107.     if (hCompatBitmap)
  1108.         DeleteObject(hCompatBitmap);
  1109.  
  1110.     if (hCompatDC)
  1111.         DeleteObject(hCompatDC);
  1112.  
  1113.     for (i=0; i<ncolor; i++) {
  1114.         if (hDrawBrush[i])
  1115.             DeleteObject(hDrawBrush[i]);
  1116.         if (hDrawPen[i])
  1117.             DeleteObject(hDrawPen[i]);
  1118.     }
  1119.     
  1120.     for (sp = selInfo; sp; sp = (select_t *) vp) {
  1121.         vp = (void *) sp->sl_next;
  1122.         GlobalFree((void *)sp->sl_rp);
  1123.         GlobalFree((void *)sp->sl_tp);
  1124.         DeleteCriticalSection(&sp->rtd_mutex);
  1125.         GlobalFree((void *) sp);
  1126.     }
  1127.     if (satInfo) {
  1128.         for (i=0; satInfo[i]; i++) {
  1129.             if (satInfo[i]->s_modep)
  1130.                 GlobalFree((void *) satInfo[i]->s_modep);
  1131.             GlobalFree((void *) satInfo[i]);
  1132.         }
  1133.         GlobalFree(satInfo);
  1134.     }
  1135.     if (siteInfo) {
  1136.         for (i=0; siteInfo[i]; i++) {
  1137.             GlobalFree((void *) siteInfo[i]->c_name);
  1138.             GlobalFree((void *) siteInfo[i]->c_locale);
  1139.             GlobalFree((void *) siteInfo[i]);
  1140.         }
  1141.         GlobalFree(siteInfo);
  1142.     }    
  1143.  
  1144.     DeleteCriticalSection(&display_mutex);
  1145.     DeleteCriticalSection(&sat_mutex);
  1146.     NormCursor();
  1147.     
  1148.     EnableWindow(GetParent(Gwnd), TRUE);
  1149.     SetFocus(GetParent(Gwnd));
  1150. }
  1151.  
  1152. /*
  1153.  * fatal - is called when an API routine returns an error when we
  1154.  * don't expect one. For example, we cant create a bitmap, or cant
  1155.  * get the dimensions of the client area (!!). Normally there is
  1156.  * nothing else to do except to terminate the program. We do make
  1157.  * an attempt to put up a message box before exiting.
  1158.  */
  1159.  
  1160. void
  1161. fatal(s)
  1162. char *s;
  1163. {
  1164.     char xbuf[256];
  1165.     sprintf(xbuf,"UNRECOVERABLE ERROR: %s (%s)",s,ErrorString(GetLastError()));
  1166.     usermsg(s);
  1167.     DestroyObjects();
  1168.     ExitProcess(1);
  1169. }
  1170.  
  1171.  
  1172. POINT *
  1173. DialogPos(pwnd, cwnd)
  1174. HWND pwnd, cwnd;    /* position cwnd in center of pwnd */
  1175. {
  1176.     RECT pr,cr;
  1177.     static POINT p;
  1178.  
  1179.     GetClientRect(pwnd,&pr);
  1180.     GetClientRect(cwnd,&cr);
  1181.  
  1182.     p.x = p.y = 0;
  1183.     ClientToScreen(pwnd,&p);  /* upper left corner of parent on screen */
  1184.     if ((p.x < 20) || (p.x + (pr.right - pr.left)) > (maxx_device+20)) {
  1185.         pr.left = 0;
  1186.         pr.right = maxx_device;
  1187.         p.x = 0;
  1188.     }
  1189.     if ((p.y < 20) || (p.y + (pr.bottom - pr.top)) > (maxy_device+20)) {
  1190.         pr.top = 0;
  1191.         pr.bottom = maxy_device;
  1192.         p.y = 0;
  1193.     }
  1194.     p.x += ((pr.right - pr.left) - (cr.right - cr.left)) / 2;
  1195.     p.y += ((pr.bottom - pr.top) - (cr.bottom - cr.top + extra_y)) / 2;
  1196.     
  1197.     return &p;
  1198. }
  1199.  
  1200.  
  1201. #if 0
  1202. static int
  1203. OppositeColor(c)
  1204. int c;
  1205. {
  1206.     int i;
  1207.     int cc = Colors[c] ^ 0xffffff;
  1208.  
  1209.     for (i=0; i< ncolor; i++)
  1210.         if ((int)Colors[i] == cc)
  1211.             return i;
  1212.     return c;
  1213. }
  1214. #endif
  1215.  
  1216. #ifdef MAPALIGN
  1217. static void
  1218. MapPoint(lat, lon, op, name)
  1219. double lat, lon;
  1220. int op;
  1221. char *name;
  1222. {
  1223.     RECT r;
  1224.     int x, y, dummy;
  1225.     SIZE sz;
  1226.     extern void convcoord(double, double, int *, int *);
  1227.  
  1228.     convcoord(lat, lon, &x, &y);
  1229.     display_lock();
  1230.  
  1231.     Ellipse(hCompatDC, x - 3, y - 3, x + 3, y + 3);
  1232.     DrawTextStr(hCompatDC, x + 5, y - 9, op, TextColor, CBLACK, hArial, name, &sz);
  1233.     r.left   = x - 4;
  1234.     r.right  = r.left + 8 + sz.cx + 1;
  1235.     r.top    = y - 10;
  1236.     r.bottom = r.top + MAX(12, sz.cy) + 1;    
  1237.     RedrawScreen(&r)
  1238.     display_unlock();
  1239. }
  1240. #endif
  1241.  
  1242. void
  1243. DrawTextStr(HDC hDC, int x, int y, int op, int textcolor, int bkcolor, HFONT hfont, char *msg, SIZE *sizep)
  1244. {
  1245.     RECT r;
  1246.     SIZE sz;
  1247.     int len = strlen(msg);
  1248.     
  1249.     if (sizep == NULL)
  1250.         sizep = &sz;
  1251.     
  1252.     SelectObject(htDC, hfont);
  1253.     GetTextExtentPoint(htDC, msg, len, sizep);
  1254.  
  1255.     r.left = r.top = 0;
  1256.     r.right = sizep->cx + 1;
  1257.     r.bottom = sizep->cy + 2;
  1258.  
  1259.     FillRect(htDC, &r, hDrawBrush[bkcolor]);
  1260.     ColorSet((WPARAM) htDC, textcolor, bkcolor);
  1261.     TextOut (htDC, 0, 0, msg, len);
  1262.  
  1263.     BitBlt(hDC, x, y, sizep->cx, sizep->cy, htDC, 0, 0, op);
  1264. }
  1265.  
  1266. void
  1267. ColorSet(wp, tcol, bkcol)
  1268. WPARAM wp;
  1269. int tcol, bkcol;
  1270. {
  1271.     SetBkColor((HDC) wp, Colors[bkcol]);
  1272.     SetTextColor((HDC) wp, Colors[tcol]);
  1273. }
  1274.  
  1275. void
  1276. NormCursor()
  1277. {    
  1278.     SetWindowText(Gwnd, VersionStr);
  1279.     SetCursor(hcurSave);
  1280.        SetClassLong(Gwnd, GCL_HCURSOR, (LONG) hcurSave);
  1281. }
  1282.  
  1283. void
  1284. WaitCursor()
  1285. {
  1286.     SetCursor(hWait);
  1287.     SetClassLong(Gwnd, GCL_HCURSOR, (LONG) hWait);
  1288.     SetWindowText(Gwnd,"Please Wait...");
  1289. }
  1290.  
  1291. void
  1292. setwsize(hWnd, flag)
  1293. HWND hWnd;
  1294. BOOL flag;
  1295. {
  1296.     int wysize, wxsize;
  1297.     
  1298.     wysize = height + extra_y + ytop + ((flag) ? ybottom-1 : 0);
  1299.     if (wysize > maxy_device) {
  1300.         wysize = maxy_device;
  1301.     }
  1302.  
  1303.     wxsize = width + extra_x;
  1304.     if (wxsize > maxx_device)
  1305.         wxsize = maxx_device;
  1306. #ifdef _DEBUG_
  1307.     diag("map: minX %lf maxX %lf minY %lf maxY %lf\n",
  1308.         mapdata.m_minx, mapdata.m_maxx, mapdata.m_miny, mapdata.m_maxy);
  1309. #endif /* _DEBUG_ */
  1310.     ScaleX = (double)width / (mapdata.m_maxx - mapdata.m_minx);
  1311.     ScaleY = (double)height / (mapdata.m_maxy - mapdata.m_miny);
  1312.     SetWindowPos(hWnd, 0, (int)0, (int)0, wxsize, wysize,
  1313.             SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
  1314. }
  1315.  
  1316. static void vsthelp()
  1317. {
  1318.     PROCESS_INFORMATION  pinfo;
  1319.     STARTUPINFO si;
  1320.     char *cp;
  1321.     BOOL r;
  1322.  
  1323.     for (cp = (char *)&si; cp < ((char *)&si + sizeof si);)
  1324.         *cp++ = 0;
  1325.  
  1326.     si.lpTitle = "VersaTrack Help";
  1327.     si.dwXSize = width;
  1328.     si.dwYSize = height / 2;
  1329.     si.dwXCountChars = 90;
  1330.     si.dwYCountChars = 26;
  1331.     si.wShowWindow = SW_SHOW;
  1332.     si.dwFlags = STARTF_USESIZE | STARTF_USEPOSITION | STARTF_USESHOWWINDOW |
  1333.         STARTF_USECOUNTCHARS;
  1334.  
  1335.     sprintf(tmpbuf,"winhlp32 %s\\versatrk.hlp", datadir);
  1336.  
  1337.     r = CreateProcess(NULL, tmpbuf, NULL, NULL, TRUE, IDLE_PRIORITY_CLASS,
  1338.         datadir, NULL, &si, &pinfo);
  1339.     if (r == FALSE) {
  1340.         sprintf(tmpbuf,"Unable to create winhlp32. Error code %d",GetLastError());
  1341.         usermsg(tmpbuf);
  1342.     }
  1343. }
  1344.  
  1345.  
  1346. static BOOL CALLBACK
  1347. VSTMenuProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1348. {
  1349.     switch (message) {
  1350.     case WM_INITDIALOG:
  1351.         SendDlgItemMessage(hWnd, IDMD_RADCNTRL, WM_SETTEXT, (WPARAM)0,
  1352.             (LPARAM) (radInfo ? radInfo[0].rad_name : "Radio ?"));
  1353.         SendDlgItemMessage(hWnd, IDMD_ROTCNTRL, WM_SETTEXT, (WPARAM)0,
  1354.             (LPARAM) (rotInfo ? rotInfo[0].rot_name : "Rotator ?"));
  1355.         SetWindowPos(hWnd, 0, 0, 0, 0, 0,
  1356.             SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
  1357.         hMenuCursor = (HCURSOR) GetClassLong(hWnd, GCL_HCURSOR);
  1358.         break;;
  1359.  
  1360.      case WM_COMMAND:
  1361.         if (HIWORD(wParam) == BN_CLICKED) {
  1362.             if (LOWORD(wParam) == IDMD_PROPMODEL) {
  1363.                 if (running || duration_running)
  1364.                     usermsg("Stop RTD and/or GTR first!");
  1365.                 else if (modelflag == TLEMEAN) {
  1366.                     SendDlgItemMessage(hWnd, IDMD_PROPMODEL, WM_SETTEXT,
  1367.                         (WPARAM) 0, (LPARAM) "SGP4");
  1368.                     modelflag = NORADSGP4;
  1369.                 }
  1370.                 else if (modelflag == NORADSGP4) {
  1371.                     SendDlgItemMessage(hWnd, IDMD_PROPMODEL, WM_SETTEXT,
  1372.                         (WPARAM) 0, (LPARAM) "TLE Mean");
  1373.                     modelflag = TLEMEAN;
  1374.                 }
  1375.                 return TRUE;
  1376.             }
  1377.             PostMessage(Gwnd, WM_COMMAND, wParam, lParam);
  1378.             return TRUE;
  1379.         }
  1380.         break;
  1381.  
  1382.     case WM_CTLCOLORBTN:
  1383.     case WM_CTLCOLORDLG:
  1384.         ColorSet(wParam, CWHITE, 8);
  1385.         return (BOOL) hDrawBrush[8];
  1386.         
  1387.     case WM_CLOSE:
  1388.         return TRUE;
  1389.     
  1390.     }
  1391.     return FALSE;
  1392. }
  1393.  
  1394. void
  1395. RedrawScreen(RECT *rp)
  1396. {
  1397.     InvalidateRect(Gwnd, rp, FALSE);
  1398. #if 0
  1399.     UpdateWindow(Gwnd);
  1400. #else
  1401.     RedrawWindow(Gwnd, rp, NULL,
  1402.         RDW_NOERASE|RDW_INTERNALPAINT|RDW_INVALIDATE|RDW_UPDATENOW);
  1403. #endif
  1404. }
  1405.  
  1406.